package com.haiyi.activiti.engine.framework.database;

import com.haiyi.activiti.engine.exception.TooManyResultException;
import com.haiyi.activiti.engine.util.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.List;

/**
 * <p> 公共的链式查询的父类 </p>
 *
 * <pre> Created: 2018/12/3 14:54 </pre>
 *
 * @author hlu
 * @version 1.0
 * @since JDK 1.7
 */
public abstract class AbstractQuery<Q extends Query<?,?>,R extends Serializable,S extends HaiyiService>
        implements Query<Q,R>, Serializable {

    private String orderBy;
    private String limitBefore;
    private String limitAfter;

    private static final String limitBeforeTemplate = "select * from (select tmp.*, rownum from (";
    private static final String limitAfterTemplate = ") tmp) where rownum>=%s and rownum<=%s";

    @Autowired
    protected S baseService;

    @Override
    public Q asc(String column) {
        Assert.isNotEmpty(column,"被排序的列不能为空！");
        addOrder(column,"asc");
        return (Q)this;
    }

    @Override
    public Q desc(String column) {
        Assert.isNotEmpty(column,"被排序的列不能为空！");
        addOrder(column,"desc");
        return (Q)this;
    }

    @Override
    public R singleResult() {
        final List<R> resultList = list();
        if(CollectionUtils.isEmpty(resultList)){
            return null;
        }else{
            if(resultList.size()==1){
                return resultList.get(0);
            }else{
                throw new TooManyResultException(resultList.size());
            }
        }
    }

    protected void addOrder(String column,String sortOrder){
        if (orderBy == null) {
            orderBy = "";
        } else {
            orderBy = orderBy + ", ";
        }

        orderBy += column + " " + sortOrder;
    }


    @Override
    public List<R> listPage(long firstResult, long maxResults) {
        if(maxResults<firstResult){
            throw new IllegalArgumentException("maxResults不能大于firstResult");
        }
        this.limitBefore = limitBeforeTemplate;
        this.limitAfter = String.format(limitAfterTemplate,firstResult,maxResults);
        return list();
    }

    @Override
    public long count() {
        return baseService.count(this);
    }

    @Override
    public List<R> list() {
        return baseService.query(this);
    }

    @Override
    public List<R> listPage2(long currentPage, long size) {
        return listPage((currentPage-1)*size+1,currentPage*size);
    }

    public String getLimitBefore() {
        return limitBefore;
    }

    public String getLimitAfter() {
        return limitAfter;
    }
}
